(() => {
    // 静态属性，这些属性在类本身而不是实例身上，通过类本身访问
    class Grid {
        constructor(public scale: number) { }
        static origin = { x: 0, y: 0 }
        calculateDistanceFromOrigin(point: { x: number, y: number }) {
            let xDist = (point.x - Grid.origin.x)
            let yDist = (point.y - Grid.origin.y)

            return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale
        }
    }
    const grid1 = new Grid(1.0)
    const grid2 = new Grid(5.0)

    console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }));
    console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }));


    // 抽象类，作为派生类的基类使用
    // 1.不能被实例化
    // 2.抽象方法必须在派生类实现
    abstract class Animal {
        constructor(public name: string) { }
        drink(): void { }
        // 定义抽象方法，在基类中不能有具体实现
        abstract makeSoud(): void
    }
    class Cat extends Animal {
        constructor(name: string) { super(name) }
        // 实现基类的抽象方法
        makeSoud(): void {
            console.log('喵喵喵');
        }
        // 实例方法
        skill(): void {
            console.log('我会捕鱼');
        }
    }
    // 抽象类不能实例化
    // const animal:Animal = new Animal()

    const cat: Animal = new Cat('小猫')
    cat.makeSoud()
    // 父类型指向子类型对象，子类型对象上的方法，必须符合父类型
    // cat.skill()


    // 定义类的时候，就定义了一个类型
    // 定义类的时候，就定义了一个构造函数
    class Greeter {
        static msg: string = '静态属性'
        greeting: string
        greet() {
            if (this.greeting) {
                return '实例属性' + this.greeting
            } else {
                return Greeter.msg
            }
        }
    }
    const greeter: Greeter = new Greeter()
    console.log(greeter.greet());

    const greeterFn: typeof Greeter = Greeter
    greeterFn.msg = '修改静态属性'

    const greeter2: Greeter = new Greeter()
    console.log(greeter2.greet());

    
    // 接口可以继承类
    class Point {
        x: number
        y: number
    }
    interface Point3d extends Point {
        z: number
    }
    let point3d: Point3d = { x: 1, y: 2, z: 3 }
})()